﻿/// <reference path="../jquery-1.4.4.js" />
/// <reference path="../jquery-1.4.4-vsdoc.js" />

/*!  
** Copyright (c) 2011 Ray Liang (http://www.dotnetage.com)
** Dual licensed under the MIT and GPL licenses:
** http://www.opensource.org/licenses/mit-license.php
** http://www.gnu.org/licenses/gpl.html
** 
**----------------------------------------------------------------
** title        : DJME RichTextBox
** version   : 2.0.1
** modified: 2011-5-20
** depends:
**    jquery.ui.core.js
**    jquery.ui.widget.js
**   
**----------------------------------------------------------------
*/

(function ($) {
    domParser = function (element) {
        this.element = $(element);
    }

    domParser.prototype = {
        isBold: function () { return (this.isIn("strong") || this.isIn("b") || this.hasStyle("font-weight", "bold")) ? true : false; },
        isItalic: function () { return (this.isIn("i") || this.hasStyle("font-style", "italic")) ? true : false; },
        isUnderline: function () { return (this.isIn("u") || this.hasStyle("text-decoration", "underline")) ? true : false; },
        isOverline: function () { return (this.hasStyle("text-decoration", "overline")) ? true : false; },
        isLineThrough: function () { return (this.hasStyle("text-decoration", "line-through")) ? true : false; },
        isLink: function () { return (this.isTag("A") || this.isIn("a")) ? true : false; },
        isJustifyLeft: function () { return (this.hasStyle("text-align", "left")) ? true : false; },
        isJustifyCenter: function () { return (this.isIn("center") || this.hasStyle("text-align", "center")) ? true : false; },
        isJustifyRight: function () { return (this.hasStyle("text-align", "right")) ? true : false; },
        isJustifyNone: function () { return (!this.isJustifyCenter() && !this.isJustifyLeft() && !this.isJustifyRight()) ? true : false; },
        isOrderList: function () { return this.isIn("ol") ? true : false; },
        isUnorderList: function () { return this.isIn("ul") ? true : false; },
        isSub: function () { return this.isIn("sub") ? true : false; },
        isSup: function () { return this.isIn("sup") ? true : false; },
        getFontFarmily: function () { return this.element.css("font-family") ? this.element.css("font-family") : "inherit"; },
        getForeColor: function () { return this.element.css("color") ? this.element.css("color") : "inherit"; },
        getBackgroundColor: function () { return this.element.css("background-color") ? this.element.css("background-color") : "inherit"; },
        getFontSize: function () { return this.element.css("font-size") ? this.element.css("font-size") : "inherit"; },
        isTag: function (_tagName) { return this.getTagName() == _tagName ? true : false; },
        isIn: function (_tagName) { return this.element.closest(_tagName).length ? true : false; },
        hasStyle: function (_name, _value) {
            if (this.element.css(_name)) {
                return this.element.css(_name).toString().toLocaleLowerCase().indexOf(_value) > -1;
            }
            else
                return false;
        },
        getTagName: function () { return this.element[0].tagName; }
    };

    $.widget("ui.richtextbox", {
        options: {
            mode: "editor",
            width: "auto",
            height: 300,
            bgColor: "white",
            border: 0,
            textFontSize: "12",
            textBGColor: "white",
            textFont: "Verdana, Arial, Helvetica",
            documentStyle: false,
            normalized: null,
            autoEncode: false
        },
        _create: function () {
            var self = this, opts = this.options, eventPrefix = this.widgetEventPrefix, el = this.element;


            self.buildEditor();
            self.initEditor(this.getText());
            self.toggleMode(opts.mode);
            if (opts.normalized)
                el.bind(eventPrefix + "normalized", opts.normalized);
        },
        _triggerEvent: function (eventName, eventArgs) {
            this.element.trigger(this.widgetEventPrefix + eventName, eventArgs);
        },
        destroy: function () {
            $.Widget.prototype.destroy.call(this);
        },
        widget: function () {
            return this.rteContainer;
        },
        syncContent: function (mode) {
            if (mode == 'editor') {
                //var c = this.getText();
                this.setHtml(this.getText());
                //alert(this.element.val());
            }
            else {
                var content = this.getHtml();
                this.setText(content);
            }
        },
        getHtml: function () {
            if (this.editor.document)
                return this.editor.document.body.innerHTML;
            else {
                this.initEditor(this.getText());
                return this.element.val();
            }
        },
        active: function () {
            if (this.editor.document == undefined || this.editor.document == null)
                this.initEditor(this.getText());
            this.editor.focus();
        },
        setHtml: function (content) {
            this.editor.document.body.innerHTML = content;
        },
        setText: function (content) {
            this.isIE() ? this.element.val(content) : this.element.val(content);
        },
        getText: function () {
            return this.isIE() ? this.element.val() : this.element.val();
        },
        execCmd: function (command, option) {
            if (this.editor) {
                if (option == 'removeFormat') {
                    command = option;
                    option = null;
                }
                try {
                    //fix the selection lost issuse
                    if (this.isIE() && this.curSelection)
                        this.curSelection.select();
                    this.editor.document.execCommand(command, false, option);
                }
                catch (e) {
                    alert(command + ": not supported");
                }
                this.editor.focus();
            }
        },
        fixIEBreak: function () {
            var self = this;
            if (this.isIE()) {
                var _doc = $(this.editor.document);

                //fix the ie will auto lose the focus that could not executeCommand
                _doc.bind("mouseup", function () {
                    if (self.isIE()) {
                        if (self.editor.document.selection)
                            self.curSelection = self.editor.document.selection.createRange();
                        else
                            self.curSelection = 0;
                    }
                });

                //fix the ie auto generate the p tag as break 
                _doc.bind("keyup", function (event) {
                    if (event.keyCode == 13) {
                        var formmated = self.getHtml().replace(/<P>&nbsp;<\/P>/ig, "")
                                                                                      .replace(/<P>/ig, "")
                                                                                      .replace(/<\/P>/ig, "<br/>");
                        self.setHtml(formmated);
                    }
                });
            }
        },
        setBold: function () { this.runCmd("Bold"); },
        setItalic: function () { this.runCmd("Italic"); },
        setUnderline: function () { this.runCmd("Underline"); },
        setStrikeThrough: function () { this.runCmd("StrikeThrough"); },
        setJustifyLeft: function () { this.runCmd("JustifyLeft"); },
        setJustifyCenter: function () { this.runCmd("JustifyCenter"); },
        setJustifyRight: function () { this.runCmd("JustifyRight"); },
        setJustifyFull: function () { this.runCmd("Justifyfull"); },
        setFontName: function (_name) { this.runCmd("fontName", _name); },
        setFontSize: function (_size) { this.runCmd("fontSize", _size) },
        insertOrderedList: function () { this.runCmd("InsertOrderedList"); },
        insertUnorderedList: function () { this.runCmd("InsertUnorderedList"); },
        setIndent: function () { this.runCmd("Indent"); },
        setOutdent: function () { this.runCmd("Outdent"); },
        setForeColor: function (_color) { this.runCmd("forecolor", _color); },
        setBackgroundColor: function (_color) { this.runCmd("hilitecolor", _color); },

        setSuperscript: function () { this.runCmd("Superscript"); },
        setSubscript: function () { this.runCmd("Subscript"); },
        insertHorizontalRule: function () { this.runCmd("InsertHorizontalRule"); },
        insertParagraph: function () { this.runCmd("InsertParagraph"); },
        insertDate: function () { this.runCmd("insertHTML", "<span>" + (new Date()).toDateString() + "</span>"); },
        insertTime: function () { this.runCmd("insertHTML", "<span>" + (new Date()).toLocaleTimeString() + "</span>"); },

        unlink: function () { this.runCmd("Unlink"); },
        removeFormat: function () { this.runCmd("RemoveFormat"); },
        copy: function () { this.runCmd("Copy"); },
        cut: function () { this.runCmd("Cut"); },
        paste: function () { this.runCmd("Paste"); },
        print: function () { this.runCmd("Print"); },
        runCmd: function (cmd, opt) {
            if (this.isIE() && !this.curSelection) {
                this.editor.focus();
                this.curSelection = this.editor.document.selection.createRange();
            }
            if (cmd && opt) {
                if (cmd == 'insertHTML' && this.isIE()) this.curSelection.pasteHTML(opt);
                else this.execCmd(cmd, opt);
            }
            else if (cmd) this.execCmd(cmd);
            if (this.isIE()) this.curSelection = 0;
        },
        toggleview: function () {
            if (this.curMode == "source")
                this.toggleMode("editor");
            else
                this.toggleMode("source");
            //this.resize();
        },
        toggleMode: function (mode) {
            var el = this.element;
            if (mode == "source") {
                //disable the toolbar
                $(this.rteiFrame).hide();
                el.show().focus();
            }
            else {
                el.hide();
                $(this.rteiFrame).show();
                this.editor.focus();
            }
            this.syncContent(mode);
            this.curMode = mode;
        },
        resize: function () {
            var el = this.element, _parent = el.parent(),
            _w = _parent.width() ? _parent.width() + "px" : "100%",
            _h = _parent.height() ? _parent.height() + "px" : "100%";

            $(this.rteiFrame).css({
                height: _h,
                width: _w
            });

            el.css({
                height: _h,
                width: _w
            });
        },
        buildEditor: function () {
            var self = this, opts = this.options, el = this.element,
            rteContainer = el.parent();
            var _strFrame = "<iframe src='javascript:void(0);' frameborder='0' style='width:100%;'></iframe>";
            rteContainer.css({ "background-color": opts.bgColor })
                               .html(_strFrame);
            el.appendTo(rteContainer);
            el.css({
                "background-color": opts.textBGColor,
                "border": opts.border
            });

            //            if (self.isIE()) {
            //                var ieW = (opts.width == "auto" || opts.width == "100%") ? "100%" : (opts.width + 3) + "px";
            //                el.css({
            //                    "overflow": "auto",
            //                    width: ieW
            //                });
            //            }

            this.rteiFrame = $("iframe", rteContainer)[0];
            this.rteContainer = rteContainer;
            this.resize();
        },
        getRTE: function () {
            return this;
        },
        getEditor: function () {
            var e = false;
            if (this.isGecko()) e = this.rteiFrame.contentWindow;
            else if (this.isIE()) e = this.rteiFrame.contentWindow;

            if (e && !this.isDesignModeSupported()) e = false;
            return e;
        },
        increaseHeight: function () {
            this._setHeight(this.element.height() + 100);
        },
        reduceHeight: function () {
            if (this.element.height() > 120)
                this._setHeight(this.element.height() - 100);
        },
        _setHeight: function (_height) {
            $(this.rteiFrame).css("height", _height ? _height : "100%");
            this.element.css("height", _height ? _height : "100%");
        },
        isDesignModeSupported: function () {
            return (document.designMode && document.execCommand) ? true : false;
        },
        isGecko: function () { return (navigator.userAgent.indexOf('Gecko') != -1) ? true : false; },
        isIE: function () { return $.browser.msie; },
        initEditor: function (content) {
            var self = this, opts = this.options, el = this.element;
            if (this.editor = this.getEditor()) {
                var _styles = '<style> ' +
                                     'BODY { ' +
                                     'margin: 4px; ' +
                                     'background-color: ' + opts.textBGColor + '; ' +
                                     '} ' +
                                     'BODY, TD, TH { ' +
                                     'color: black; ' +
                                     'font-family: ' + opts.textFont + '; ' +
                                     'font-size: ' + opts.textFontSize + 'px; ' +
                                     '} ' +
                                     'TD { border: 1px dashed silver; } ' +
                                     'P { margin: 0px; } ' +
                                     '</style>';
                if (this.options.documentStyle) {
                    _styles = "";

                    $.each(document.styleSheets, function (i, n) {
                        _styles += '<link href="' + n.href + '" type="text/css" rel="stylesheet">';
                    });
                }

                var html = '<html><head>' + _styles + '</head>' +
                                     '<body style="background:none;">' +
                                     content.replace(/<STYLE>[^<]+<\/STYLE>(\r?\n)*/gi, '') +
                                     '</body></html>';
                this.editor.document.designMode = 'on';
                //if (self.isGecko()) this.editor.document.execCommand('useCSS', false, true);
                this.editor.document.open();
                this.editor.document.write(html);
                this.editor.document.close();
                if (this.setFocus) this.editor.focus();

                //$(this.rteiFrame.contentWindow).bind("pageshow", function () { alert("show") });

                var _normalizedHandler = function (event) {
                    if (event.target) {
                        var _parser = new domParser(event.target);
                        self._triggerEvent("normalized", _parser);
                    }
                };


                $(this.editor.document).bind("mousedown", _normalizedHandler);
                //.bind("load", function () { alert("load"); });

                // .bind("keypress",_normalizedHandler);

                var _form = el.closest("form");
                if (_form.length) {
                    _form.bind("submit", function () {
                        //encoded the html before submit
                        //self.setText(self.getHtml());
                        if (self.curMode == "editor")
                            self.syncContent("source");
                        if (opts.autoEncode) {
                            self.isIE() ? el.val(self.htmlEncode(self.getHtml())) : el.text(self.htmlEncode(self.getHtml()));
                        }
                    });
                }

                this.fixIEBreak();
            }
            else alert("Sorry, your browser doesn't support richtext editing!");
        },

        encodedHtml: function () {
            var self = this;
            if (self.curMode == "editor")
                self.syncContent("source");
            return self.htmlEncode(self.getText());
        },
        isHtmlEncode: function (strHtml) {
            if (strHtml.search(/&amp;/g) != -1 || strHtml.search(/&lt;/g) != -1 || strHtml.search(/&gt;/g) != -1)
                return true;
            else
                return false;
        },
        htmlEncode: function (strHtml) {
            if (strHtml)
                return strHtml.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
            else
                return "";
        },
        htmlDecode: function (strHtml) {
            if (this.isHtmlEncode(strHtml))
                return strHtml.replace(/&amp;/g, '&').replace(/&lt;/g, '<').replace(/&gt;/g, '>');
            return strHtml;
        },
        insertLink: function (_url, _target) {
            if (_url && _url != 'http://') {
                if (this.curSelection)
                    this.runCmd('insertHTML', '<a href="' + _url + '" target="' + _target + '">' + this.curSelection.text);
                else this.runCmd('createLink', _url);
            }
        },
        formatBlock: function (_tag) {
            if (_tag) {
                this.runCmd("formatBlock", "<" + _tag + ">");
            }
        },
        insertImage: function (_url) {
            if (_url && _url != 'http://') {
                if (this.curSelection) this.runCmd('insertHTML', '<IMG src="' + _url + '">');
                else this.runCmd('insertImage', _url);
            }
        }
    });


})(jQuery);